
#if defined (RADIONRF24)
#include "nrf24.h"

// === Lowest level ====

void nrf24_hw_init() {
    
    GPIO_InitTypeDef port;
    SPI_InitTypeDef SPI_InitStructure;
    NVIC_InitTypeDef nvic;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
    
    /******************** SPI2 - nRF24 ******************************************/
    /* SPI_MASTER configuration ------------------------------------------------*/
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(NRF24_SPI, &SPI_InitStructure);

    /* Configure NRF24_SPI pins: SCK and MOSI ---------------------------------*/
    /* Configure SCK and MOSI pins as Alternate Function Push Pull */
    GPIO_StructInit(&port);
    port.GPIO_Mode = GPIO_Mode_AF_PP;
    port.GPIO_Pin = NRF24_SPI_PIN_SCK | NRF24_SPI_PIN_MOSI ;
    port.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(NRF24_SPI_GPIO, &port);
    
    /* Configure MISO pin as Input */
    GPIO_StructInit(&port);
    port.GPIO_Mode = GPIO_Mode_IPD;
    port.GPIO_Pin = NRF24_SPI_PIN_MISO ;
    GPIO_Init(NRF24_SPI_GPIO, &port);
    
    /* Configure CSN pin as Push Pull */
    GPIO_StructInit(&port);
    port.GPIO_Mode = GPIO_Mode_Out_PP;
    port.GPIO_Pin = NRF24_PIN_CE ;
    port.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(NRF24_AUX_GPIO, &port);
    
    /* Configure CE pin as Push Pull */
    GPIO_StructInit(&port);
    port.GPIO_Mode = GPIO_Mode_Out_PP;
    port.GPIO_Pin = NRF24_SPI_PIN_NSS ;
    port.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(NRF24_SPI_GPIO, &port);
  
    /* Configure and enable NRF24_SPI interrupt -------------------------------*/
    nvic.NVIC_IRQChannel = NRF24_SPI_IRQn;
    nvic.NVIC_IRQChannelPreemptionPriority = 1;
    nvic.NVIC_IRQChannelSubPriority = 2;
    nvic.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&nvic);
    
    NRF24_CS_HIGH;
    NRF24_STBY;
    
    SPI_Cmd(NRF24_SPI, ENABLE);
}

uint8_t nrf24_ReadByte(SPI_TypeDef * NRF)
{
    while (!(NRF->SR & SPI_I2S_FLAG_TXE));
    NRF->DR = 0xFF;
    while (!(NRF->SR & SPI_I2S_FLAG_RXNE));
    return NRF->DR ;
}

uint8_t nrf24_WriteByte(SPI_TypeDef * NRF, uint8_t w)
{
    NRF->DR = w;
    while (!(NRF->SR & SPI_I2S_FLAG_RXNE));
    return NRF->DR ;
}

// === Low level ===

uint8_t nrf24_WriteData(SPI_TypeDef * NRF, uint8_t regnumber, uint8_t * data, int len)
{
    uint8_t status = 0;
    
    nrf24_Select();
    status = NRF->DR; // Clear DR
    status = nrf24_WriteByte(NRF, NRF_W_REGISTER | regnumber);
    while (len) {
        nrf24_WriteByte(NRF, data[--len]);
    }
    nrf24_Deselect();
   
    return status;
}

uint8_t nrf24_ReadData(SPI_TypeDef * NRF, uint8_t regnumber, uint8_t * data, int len)
{
    uint8_t status = 0;

    nrf24_Select();
    status = NRF->DR; // Clear DR
    status = nrf24_WriteByte(NRF, NRF_R_REGISTER | regnumber);
    while (len--) {
        *data ++ = nrf24_ReadByte(NRF);
    }    
    nrf24_Deselect();
    
    return status;
}

uint8_t nrf24_WriteRegister(SPI_TypeDef * NRF, uint8_t regnumber, uint8_t data)
{
    return nrf24_WriteData(NRF, regnumber, &data, 1);
}

uint8_t nrf24_ReadRegister(SPI_TypeDef * NRF, uint8_t regnumber)
{
    uint8_t status = 0;

    nrf24_ReadData(NRF, regnumber, &status, 1);
    
    return status;
}

// === Middle layer ===

void startNRF24(void){
     /*
     * Initialize Mutex
     */

    /*
     * Initialize the FIFO semaphores
     */

    /*
     * Set configuration registers
     */
    nrf24_WriteRegister(NRF24_SPI, NRF_REG_CONFIG, 0x0E);   /* POWER_UP, ENABLE CRC                   */
#if defined (COOLBIC)
    nrf24_WriteRegister(NRF24_SPI, NRF_REG_EN_AA, 0x03);                  /* Enhanced ShockBurst on channel 0,1   */
    nrf24_WriteRegister(NRF24_SPI, NRF_REG_EN_RXADDR, 0x03);                  /* Enable data pipe 0,1                                                         */
    nrf24_WriteRegister(NRF24_SPI, NRF_REG_SETUP_AW, 0x02);                    /* 5 bytes address width                                                        */
    nrf24_WriteRegister(NRF24_SPI, NRF_REG_SETUP_RETR, 0x13);                      /* Up to 3 Re-Transmit, Wait 500µS              */
    nrf24_WriteRegister(NRF24_SPI, NRF_REG_RF_SETUP, 0x07); /* Sets up the channel we work on: Data Rate 1Mbps Pwr 0dBm            */
    nrf24_WriteRegister(NRF24_SPI, NRF_REG_STATUS, 0x70);   /* Reset the IRQ registers.                                            */
    nrf24_WriteRegister(NRF24_SPI, NRF_REG_RX_PW_P0      , NRF_FIFO_BYTES);      /* Pipe 0 FIFO holds 32 bytes.                          */
    nrf24_WriteRegister(NRF24_SPI, NRF_REG_RX_PW_P1      , NRF_FIFO_BYTES);      /* Pipe 1 FIFO holds 32 bytes.                          */
    
#elif defined (COOLPAD)


#endif /* COOLPAD / COOLBIC */

    /*
     * Set CE to high, to put NRF24L01 into Receive mode.
     */
    NRF24_ACTIVE;
    nrf24_ReadRegister(NRF24_SPI, NRF_REG_RF_SETUP); 

}
uint8_t nrf24_GetStatus(void)
{
    uint8_t status;
    
    nrf24_Select();
    status = nrf24_ReadByte(NRF24_SPI);
    nrf24_Deselect();
    
    return status;
}


// tests

uint8_t nrf24_test(SPI_TypeDef * NRF)
{
    uint8_t status;
    
    nrf24_Select();
    status = nrf24_ReadByte(NRF24_SPI);
    nrf24_Deselect();
    
    return status;
}

#endif /* RADIONRF24 */
